[C++] Unreal Engine 4ゲームプログラミング for Ultra Beginners [基本][Actor]
世の数多の3DCGソフトやゲームエンジンに手を出しては心を砕かれてきた、不肖小室が、Unreal Engine 4のゲームプログラミングに挑戦してみます。
ここ最近ではメジャータイトルのゲームエンジンに採用される など色々と話題なゲームエンジンです。
背景
私が今住んでいる札幌は、ゲーム開発会社がとても活発な印象です。昨年自分が参加したGlobal Game Jam Sapporoでもプログラマー、3DCGのデザイナー、プランナーやサウンド・エンジニアの方などの方々が数多く参加されていました。そのため、ゲームに関する開発情報などが東京に居た時以上に身近に見聞きすることが多くなっています。
そして、Global Game Jamの中で強烈に高いクオリティのゲームを作り上げていた Unreal Engineチーム があり、そこで初めてUnreal Engineの開発を間近で見ることができました。そこが始まりです。
学習素材について
Unreal Engineは基本的に公式ドキュメントが非常に充実しています。これらほとんどのドキュメントは日本語化されています。そのため、初心者の人は公式ドキュメントを参照しながら学習していくのが良いようです。またTutorialのための動画もYoutubeにアップロードされていたりするため、基本を学ぶ上での学習素材にはあまり困らないのではないでしょうか。 *1
開発環境について
ワタシの開発環境はこちらです。
- OS: Windows 7 Professional 64bit
- CPU: Intel Core i5-4590 3.30GHz
- メモリ: 8GB
- IDE: Visual Studio Community 2013
- Unreal Engine: Unreal Engine 4.8.3 *2
- グラフィックカード: nVidia GeForce GTX 750 Ti
SteamでFPSをやることが多いため *3、エントリーミドルレンジあたりのコスパの良いグラフィックカードを搭載しています。開発環境としては少々メモリが貧弱かもしれません。
プロジェクトの作成
Unreal Engineを立ち上げます。Unreal Editorと呼ばれる開発環境が立ち上がります。
「C++の基本コード」を選択します。
Unreal EditorとVisual Studioが立ち上がるのでしばらく待ちます。
起動しました。準備完了。
Actorを拡張する
QuickStartにそって進めていきましょう。まずは Actor
というクラスを拡張した独自のクラスを作成します。 Actor
はオブジェクトとしての特性を持った基本的なオブジェクトのクラスです。位置情報などワールド内に存在するための情報は持たず、あくまでその物体の特徴のみを記載できるようサポートしているようです。
作り方はEditor上からポチポチと作成していきます。今回はQuickStartの通りに「FloatingActor」という名前で作成しましょう。
Editorにオブジェクトが追加されると同時に、Visual Studioのプロジェクト内に以下のファイルが追加されているのが確認できます。
- FloatingActor.h
- FloatingActor.cpp
ざっと中身を確認してみます。
ヘッダファイルを読む
#include "GameFramework/Actor.h" #include "FloatingActor.generated.h" UCLASS() class QUICKSTART_API AFloatingActor : public AActor { GENERATED_BODY() public: // Sets default values for this actor's properties AFloatingActor(); // Called when the game starts or when spawned virtual void BeginPlay() override; // Called every frame virtual void Tick( float DeltaSeconds ) override; };
UCLASS()
という表記が見えます。
後半にも出てきますが、どうやらこの U
から始まるマクロは、Unreal Editorで見たり、編集したりするために公開する変数などのための宣言に使うようです。この場合は、クラス名をUnreal Editorへ公開しているという意味で捉えれば良さそうです。
public
セクションを見ていきます。
AFloatingActor()
コンストラクタ。生成時に呼ばれます。virtual void BeginPlay() override
開始時に一度呼ばれるメソッド。vertual void Tick (float DeltaSeconds) override
1フレーム毎に呼ばれるメソッドです。オプションの設定によって、これが1フレーム毎に呼ばれるのを抑止することも出来ます。時間によってオブジェクトの情報を変化させたい場合は、ここに処理を記述していきます。
ソースファイルを読む
ソースファイルを確認します。ここにはヘッダファイルで定義した各メソッドの実装を記述されています。
// Fill out your copyright notice in the Description page of Project Settings. #include "QuickStart.h" #include "FloatingActor.h" // Sets default values AFloatingActor::AFloatingActor() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; } // Called when the game starts or when spawned void AFloatingActor::BeginPlay() { Super::BeginPlay(); } // Called every frame void AFloatingActor::Tick( float DeltaTime ) { Super::Tick( DeltaTime ); }
コンストラクタ内部で PrimaryActorTick.bCanEverTick
を true
に設定している箇所が見えます。これが true
に設定されている場合は、 AFloatingActor::Tick()
は1フレーム毎に呼ばれます。このオプションを false
にすることで時間変化による情報の更新が必要のないものや、高速に処理する必要のないものを定義することができるようです。
秒単位で更新すれば良いオブジェクトなどは1フレーム毎に更新する必要はないので、このオプションは false
に設定されるようです。
定義したActorを可視コンポーネントに結びつける
Unreal Editorに戻ります。コンテンツブラウザ の「C++クラス」という箇所の「QuickStart」を選択しましょう。「FloatingActor」という球体のサムネイルが確認できます。
これをドラッグしてプレビュー画面の中へ持っていきます。レベルエディタと呼ばれるのはこれのようです。
すると右上にある「アウトライナ」に「FloatingActor1」 が追加されます。
これを選択し、下の緑色のボタン「コンポーネントを追加」 をクリックするとオブジェクトの選択肢が出てきます。ここでは「コーン」を選択しましょう。
すると画面上にコーンがにょきっと出現します。が、見えない!カメラの位置を動かします。右クリックをしながらドラッグするとカメラの方向を変えました。
地面にめり込んでしまってるので位置を補正してテーブルの上に配置します。ロケーション のパラメータを設定します。
- x: -200.0
- y: 0.0
- z: 200.0
これでテーブルの上にふわりと浮いたコーンが出現します。
コンパイルと実行
Unreal Editor上からコンパイルできます。上部に並んでいるメニューから「コンパイル」を選択します。編集された全てのリソースをもりもりコンパイルしてくれます。Visual Studio上のコンパイルは特に実行する必要がないのかもしれません。但し、エラーが発生した場合は比較的見づらいログになるので要注意です。
コンパイル中は「C++コードをコンパイル中。。。」という表示がされます。 正常に完了すると「コンパイルが完了しました」というメッセージが通知されます。
その隣の「プレイ」を押すと、実際のゲーム画面のプレビューをプレイすることができます。 いわゆるFPSゲームと同じ動きなので、前後左右の動きはキーボードの「WSAD」、視点移動はマウスで行います。
3D酔いするひとは程よいゲロゲロ感が味わえるかと思います。
コーンを上下に浮遊させる
このままでは、単に自動生成されたコードをポチポチ配置しただけで動きがありません。さきほど画面に登場させたコーン型のコンポーネントは、定義したActorと結びついています。そのため、FloatingActor.h, FloatingActor.cpp を編集することでコンポーネントの動きが定義できます。QuickStartにそって、フワフワと浮遊させてみます。
フレームごとに呼び出されるメソッドの中に実装を記述していきます。引数として渡されている DeltaTime
はその名の通りフレームごとの差分時間が記録されているものと想像できます。
// Called every frame void AFloatingActor::Tick( float DeltaTime ) { Super::Tick( DeltaTime ); }
これらの情報を利用してオブジェクトの動作を記述していきます。まずはオブジェクトの現在位置を取得しましょう。
FVector NewLocation = GetActorLocation();
GetActorLocation()
というメソッドが親クラスの Actor
には宣言されているようです。こちらを呼び出します。
余談なのですが、宣言する変数名が大文字始まりというのが個人的にかなり違和感があります。Unreal EngineのC++文化特有のものなのでしょうか。一応、郷に入れば郷に従えの精神でこのまま進みます。
さて一度Unreal Editorに戻ってワールドの座標系を確認してみましょう。
どうも上下方向が Z軸 方向にあたるようです。ということで上下にオブジェクトを動かすためには、オブジェクトのZ座標を操作します。経過時間ごとに上下に行き来させるためには、 sin関数 を利用し 1.0f ~ -1.0f の領域を行ったり来たりするようにします。
float DeltaHeight = (FMath::Sin(RunningTime + DeltaTime) - FMath::Sin(RunningTime));
RunningTime
という変数が唐突に出てきました。これは累計経過時間を表します。クラスのメンバー変数としてヘッダに宣言します。実装については後述。
public: // Sets default values for this actor's properties AFloatingActor(); // Called when the game starts or when spawned virtual void BeginPlay() override; // Called every frame virtual void Tick( float DeltaSeconds ) override; // 累計経過時間 float RunningTime =0.0f;
DeltaHeight
はそのままでは、当然 1~-1の値の領域しか変化しません。変化させたい高さをかけてオブジェクトのZ座標へ適用します。
NewLocation.Z += DeltaHeight * 20.0f;
これにより物体は上下に 20~-20 変化することになります。最後に自分自身の位置情報を更新させます。
SetActorLocation(NewLocation); RunningTime += DeltaTime;
累計経過時間に差分時間を足し合わせるのもお忘れなく。
実行結果
早速実行してみます。ふわりふわりとテーブルの上にコーンが上下する謎の世界が出来上がりました。
おまけ
この Hello World 的チュートリアル後、発展課題が有るのですがそこに書いてあるのが
Particle System Component を FloatingActor に追加します。プロジェクトの中には、ビルド済みの パーティクル システム が幾つか含まれています。
唐突に登場するParticle System Component!後半のドキュメントを読めば使い方が書いてありました。が、Hello World直後の自分にとってはもう泳げるよ!とポーンと海のど真ん中に投げ出された感がありました。